#include "bsp_usart.h"
#include "gd32a508_usart.h"
#include <string.h>

#if USART2_OR_UART3

#define USE_UART_DMA        1

#define UART_TX_PORT        GPIOC
#define UART_TX_Pin         GPIO_PIN_10
#define UART_RX_PORT        GPIOC
#define UART_RX_Pin         GPIO_PIN_11

#define USART_X             UART3 
#define USART_RCU           RCU_UART3
#define USART_PIN_RCU       RCU_GPIOC

dv_UART_TypeDef dv_UART;

static void USART_NVIC_Config(void)
{
    nvic_irq_enable(UART3_IRQn,2,2);
}


static void BSP_UART_Deinit(void)
{
    usart_deinit(USART_X);  //复位串口
}

static void USART_GPIO_Config(void)
{
	rcu_periph_clock_enable(USART_PIN_RCU); //GPIO时钟
	rcu_periph_clock_enable(RCU_AF);        //使能AFIO时钟	
	rcu_periph_clock_enable(USART_RCU);     //使能USART时钟
	
    gpio_init(UART_TX_PORT, GPIO_MODE_AF_PP, GPIO_OSPEED_50MHZ, UART_TX_Pin);
    gpio_init(UART_RX_PORT, GPIO_MODE_IN_FLOATING, GPIO_OSPEED_50MHZ, UART_RX_Pin);        
}


static void USART_PERIPH_Config(uint32_t u32BaudRate)
{
    //USART 初始化设置
    usart_deinit(USART_X); //复位串口
    usart_baudrate_set(USART_X, u32BaudRate);
    
#if USE_UART_DMA    
    usart_dma_receive_config(USART_X, USART_RECEIVE_DMA_ENABLE);
    usart_dma_transmit_config(USART_X, USART_TRANSMIT_DMA_DISABLE);
#else   
    usart_word_length_set(USART_X, USART_WL_8BIT);
    usart_stop_bit_set(USART_X, USART_STB_1BIT);
    usart_parity_config(USART_X, USART_PM_NONE);
    usart_hardware_flow_rts_config(USART_X, USART_RTS_DISABLE);
    usart_hardware_flow_cts_config(USART_X, USART_CTS_DISABLE);
#endif
    usart_receive_config(USART_X, USART_RECEIVE_ENABLE);
    usart_transmit_config(USART_X, USART_TRANSMIT_ENABLE);

	usart_enable(USART_X);					  //使能串口
}

#if USE_UART_DMA
#define USARTX_RDATA_ADDRESS      ((uint32_t)&USART_DATA(UART3))
static void USART_DMA_Config(void)
{
    dma_parameter_struct dma_init_struct;
    
    rcu_periph_clock_enable(RCU_DMA1);
    
    dma_deinit(DMA1, DMA_CH2);

    dma_init_struct.direction = DMA_PERIPHERAL_TO_MEMORY;
    dma_init_struct.memory_addr = (uint32_t)dv_UART.u8UartData;
    dma_init_struct.memory_inc = DMA_MEMORY_INCREASE_ENABLE;
    dma_init_struct.memory_width = DMA_MEMORY_WIDTH_8BIT;
    dma_init_struct.number = UART_TX_RX_BUFFER_SIZE;
    dma_init_struct.periph_addr = USARTX_RDATA_ADDRESS;
    dma_init_struct.periph_inc = DMA_PERIPH_INCREASE_DISABLE;
    dma_init_struct.periph_width = DMA_PERIPHERAL_WIDTH_8BIT;
    dma_init_struct.priority = DMA_PRIORITY_ULTRA_HIGH;
    dma_init(DMA1, DMA_CH2, &dma_init_struct);

    /* configure DMA mode */
    dma_circulation_disable(DMA1, DMA_CH2);

    /* enable DMA channel2 */
    dma_channel_enable(DMA1, DMA_CH2);
}
#endif

static void  BSP_UART_Init(uint32_t u32BaudRate)
{
    USART_GPIO_Config();
    USART_NVIC_Config();

#if USE_UART_DMA
    USART_DMA_Config();
#endif  

    USART_PERIPH_Config(u32BaudRate);

#if USE_UART_DMA
    usart_flag_clear(USART_X, USART_FLAG_IDLE);
    usart_interrupt_enable(USART_X, USART_INT_IDLE);
#else
    while(RESET == usart_flag_get(USART_X, USART_FLAG_TC));
    usart_interrupt_enable(USART_X, USART_INT_RBNE);
#endif
}

//读空收发寄存器
static void BSP_UART_Reg_Clear (void)
{
    //先读SR，再读DR以清USART_IT_IDLE标志
    USART_STAT0(USART_X);
    USART_DATA(USART_X);
}


static uint8_t BSP_UART_Byte_Send (uint8_t u8data)
{
	uint16_t u16temp = u8data; 

    usart_data_transmit(USART_X, u16temp);
    while(usart_flag_get(USART_X, USART_FLAG_TBE) == RESET);

    return true;
}

static uint8_t BSP_UART_String_Send (uint8_t *String)
{
    uint8_t u8length = 0,i = 0;
    uint8_t* u8data = String;
    uint16_t u16temp = 0;

    u8length = strlen((char*)String);

    for(i=0; i<u8length; i++)
    {
        u16temp = *u8data;
        usart_data_transmit(USART_X, u16temp);
        while(usart_flag_get(USART_X, USART_FLAG_TBE) == RESET);  
        u8data++;
    }

    return true;
}

static  uint8_t BSP_UART_Data_Send (uint8_t *String, uint16_t u16length)
{
    uint8_t i = 0;
    uint8_t* u8data = String;
	uint16_t u16temp = 0;

    for(i=0; i<u16length; i++)
    {
		u16temp = *u8data;
        usart_data_transmit(USART_X, u16temp);
        while(usart_flag_get(USART_X, USART_FLAG_TBE) == RESET); 
        u8data++;
    }

    return true;
}


#if USE_UART_DMA
static uint16_t BSP_UART_Data_Recv (uint8_t *pData, uint16_t Timeout)
{
    volatile uint16_t u16Len = 0;
	
    if(dv_UART.u8UartRecvCnt > 0)
    {
        u16Len = dv_UART.u8UartRecvCnt;
        memcpy( pData, dv_UART.u8UartData, u16Len );

            //清接收缓存
        dv_UART.u8UartRecvCnt = 0;
        memset( dv_UART.u8UartData, 0U, UART_TX_RX_BUFFER_SIZE);        
    }
    else
    {
        u16Len = 0;
    }

    return u16Len;
}

#else

static uint16_t BSP_UART_Data_Recv (uint8_t *pData, uint16_t Timeout)
{
    volatile uint16_t u16Len = 0;
	
    if(dv_UART.u8UartRecvCnt > 0)
    {
        u16Len = dv_UART.u8UartRecvCnt;
        memcpy( pData, dv_UART.u8UartData, u16Len );

            //清接收缓存
        dv_UART.u8UartRecvCnt = 0;
        memset( dv_UART.u8UartData, 0U, UART_TX_RX_BUFFER_SIZE);
        
    }
    else
    {
        u16Len = 0;
    }    
    return u16Len;
}
#endif

#if USE_UART_DMA
void UART3_IRQHandler(void)  //串口3中断服务程序
{
    if(RESET != usart_interrupt_flag_get(UART3, USART_INT_FLAG_IDLE))
    {
        /* clear IDLE flag */
        usart_data_receive(UART3);
        
        /* number of data received */
        dv_UART.u8UartRecvCnt = 200 - (dma_transfer_number_get(DMA1, DMA_CH2));
		
        /* disable DMA and reconfigure */
        dma_channel_disable(DMA1, DMA_CH2);
        dma_transfer_number_config(DMA1, DMA_CH2, 200);
        dma_channel_enable(DMA1, DMA_CH2);		
    }  

    //先读SR，再读DR以清USART_IT_IDLE标志
    USART_STAT0(UART3);
    USART_DATA(UART3);      
}

#else
void UART3_IRQHandler(void)                	//串口3中断服务程序
{
    if(usart_interrupt_flag_get(USART_X, USART_INT_FLAG_RBNE) != RESET)
    {
        /* 关空闲中断，以防再次进入中断不便处理 ------------------------------*/
        usart_interrupt_disable(USART_X, USART_INT_RBNE );

        dv_UART.u8UartData[dv_UART.u8UartRecvCnt] = usart_data_receive(USART_X);

        if(dv_UART.u8UartRecvCnt++ >= UART_TX_RX_BUFFER_SIZE)
        {
        	dv_UART.u8UartRecvCnt = UART_TX_RX_BUFFER_SIZE;
             if( dv_UART.xUartRxSem != NULL )
            {
                xSemaphoreGiveFromISR( dv_UART.xUartRxSem, &xHigherPriTaskWoken );
                portYIELD_FROM_ISR( xHigherPriTaskWoken );
            }
        }

        /* 清中断标志 --------------------------------------------------------*/
        usart_interrupt_flag_clear(USART_X, USART_INT_FLAG_RBNE);      
        /* 处理完毕后再次开空闲中断 ------------------------------------------*/
        usart_interrupt_enable(USART_X, USART_INT_RBNE);      
    }
    
    //先读SR，再读DR以清USART_IT_IDLE标志
    USART_STAT0(USART_X);
    USART_DATA(USART_X);  
}

#endif


static void USART_RX_EN_PIN_Ctrl(bool arg)
{	
	// bit_status BitVal;
	// BitVal = (arg)?(SET):(RESET);
	// gpio_init(GPIOC, GPIO_MODE_OUT_PP, GPIO_OSPEED_50MHZ, GPIO_PIN_12);
	// gpio_bit_write(GPIOC,GPIO_PIN_12,BitVal);
}


void init_dv_UART(void)
{    
    dv_UART.u8UartRecvCnt = 0;

    memset(dv_UART.u8UartData,0,UART_TX_RX_BUFFER_SIZE);

    dv_UART.fdeinit = BSP_UART_Deinit;
    dv_UART.finit = BSP_UART_Init;
    dv_UART.fclear = BSP_UART_Reg_Clear;
    dv_UART.fwrite_byte = BSP_UART_Byte_Send;
    dv_UART.fwrite_data = BSP_UART_Data_Send;
    dv_UART.fwrite_string = BSP_UART_String_Send;
    dv_UART.fread_data = BSP_UART_Data_Recv;
	dv_UART.fRxPinCtrl = USART_RX_EN_PIN_Ctrl;
}

#else

#define USE_UART_DMA        1

#define UART_TX_PORT        GPIOC
#define UART_TX_Pin         GPIO_PIN_10
#define UART_RX_PORT        GPIOC
#define UART_RX_Pin         GPIO_PIN_11

#define USART_X             USART2 
#define USART_RCU           RCU_USART2
#define USART_PIN_RCU       RCU_GPIOC

dv_UART_TypeDef dv_UART;

static void USART_NVIC_Config(void)
{
    nvic_irq_enable(USART2_IRQn,2,2);
}


static void BSP_UART_Deinit(void)
{
    usart_deinit(USART_X);  //复位串口
}

static void USART_GPIO_Config(void)
{
	rcu_periph_clock_enable(USART_PIN_RCU); //GPIO时钟
	rcu_periph_clock_enable(RCU_AF);        //使能AFIO时钟	
	rcu_periph_clock_enable(USART_RCU);     //使能USART时钟
	
    gpio_init(UART_TX_PORT, GPIO_MODE_AF_PP, GPIO_OSPEED_50MHZ, UART_TX_Pin);
    gpio_init(UART_RX_PORT, GPIO_MODE_IN_FLOATING, GPIO_OSPEED_50MHZ, UART_RX_Pin);   
    
    gpio_pin_remap_config(GPIO_USART2_PARTIAL_REMAP,ENABLE);
}


static void USART_PERIPH_Config(uint32_t u32BaudRate)
{
    //USART 初始化设置
    usart_deinit(USART_X); //复位串口
    usart_baudrate_set(USART_X, u32BaudRate);
    
#if USE_UART_DMA    
    usart_dma_receive_config(USART_X, USART_RECEIVE_DMA_ENABLE);
    usart_dma_transmit_config(USART_X, USART_TRANSMIT_DMA_DISABLE);
#else   
    usart_word_length_set(USART_X, USART_WL_8BIT);
    usart_stop_bit_set(USART_X, USART_STB_1BIT);
    usart_parity_config(USART_X, USART_PM_NONE);
    usart_hardware_flow_rts_config(USART_X, USART_RTS_DISABLE);
    usart_hardware_flow_cts_config(USART_X, USART_CTS_DISABLE);
#endif
    usart_receive_config(USART_X, USART_RECEIVE_ENABLE);
    usart_transmit_config(USART_X, USART_TRANSMIT_ENABLE);

	usart_enable(USART_X);					  //使能串口
}

#if USE_UART_DMA
#define USARTX_RDATA_ADDRESS      ((uint32_t)&USART_DATA(USART2))
static void USART_DMA_Config(void)
{
    dma_parameter_struct dma_init_struct;
    
    rcu_periph_clock_enable(RCU_DMA0);
    
    dma_deinit(DMA0, DMA_CH2);

    dma_init_struct.direction = DMA_PERIPHERAL_TO_MEMORY;
    dma_init_struct.memory_addr = (uint32_t)dv_UART.u8UartData;
    dma_init_struct.memory_inc = DMA_MEMORY_INCREASE_ENABLE;
    dma_init_struct.memory_width = DMA_MEMORY_WIDTH_8BIT;
    dma_init_struct.number = UART_TX_RX_BUFFER_SIZE;
    dma_init_struct.periph_addr = USARTX_RDATA_ADDRESS;
    dma_init_struct.periph_inc = DMA_PERIPH_INCREASE_DISABLE;
    dma_init_struct.periph_width = DMA_PERIPHERAL_WIDTH_8BIT;
    dma_init_struct.priority = DMA_PRIORITY_ULTRA_HIGH;
    dma_init(DMA0, DMA_CH2, &dma_init_struct);

    /* configure DMA mode */
    dma_circulation_disable(DMA0, DMA_CH2);

    /* enable DMA channel2 */
    dma_channel_enable(DMA0, DMA_CH2);
}
#endif

static void  BSP_UART_Init(uint32_t u32BaudRate)
{
    USART_GPIO_Config();
    USART_NVIC_Config();

#if USE_UART_DMA
    USART_DMA_Config();
#endif  

    USART_PERIPH_Config(u32BaudRate);

#if USE_UART_DMA
    usart_flag_clear(USART_X, USART_FLAG_IDLE);
    usart_interrupt_enable(USART_X, USART_INT_IDLE);
#else
    while(RESET == usart_flag_get(USART_X, USART_FLAG_TC));
    usart_interrupt_enable(USART_X, USART_INT_RBNE);
#endif
}

//读空收发寄存器
static void BSP_UART_Reg_Clear (void)
{
    //先读SR，再读DR以清USART_IT_IDLE标志
    USART_STAT0(USART_X);
    USART_DATA(USART_X);
}


static uint8_t BSP_UART_Byte_Send (uint8_t u8data)
{
	uint16_t u16temp = u8data; 

    usart_data_transmit(USART_X, u16temp);
    while(usart_flag_get(USART_X, USART_FLAG_TBE) == RESET);

    return true;
}

static uint8_t BSP_UART_String_Send (uint8_t *String)
{
    uint8_t u8length = 0,i = 0;
    uint8_t* u8data = String;
    uint16_t u16temp = 0;

    u8length = strlen((char*)String);

    for(i=0; i<u8length; i++)
    {
        u16temp = *u8data;
        usart_data_transmit(USART_X, u16temp);
        while(usart_flag_get(USART_X, USART_FLAG_TBE) == RESET);  
        u8data++;
    }

    return true;
}

static  uint8_t BSP_UART_Data_Send (uint8_t *String, uint16_t u16length)
{
    uint8_t i = 0;
    uint8_t* u8data = String;
	uint16_t u16temp = 0;

    for(i=0; i<u16length; i++)
    {
		u16temp = *u8data;
        usart_data_transmit(USART_X, u16temp);
        while(usart_flag_get(USART_X, USART_FLAG_TBE) == RESET); 
        u8data++;
    }

    return true;
}


#if USE_UART_DMA
static uint16_t BSP_UART_Data_Recv (uint8_t *pData, uint16_t Timeout)
{
    volatile uint16_t u16Len = 0;
	
    if(dv_UART.u8UartRecvCnt > 0)
    {
        u16Len = dv_UART.u8UartRecvCnt;
        memcpy( pData, dv_UART.u8UartData, u16Len );

            //清接收缓存
        dv_UART.u8UartRecvCnt = 0;
        memset( dv_UART.u8UartData, 0U, UART_TX_RX_BUFFER_SIZE);        
    }
    else
    {
        u16Len = 0;
    }

    return u16Len;
}

#else

static uint16_t BSP_UART_Data_Recv (uint8_t *pData, uint16_t Timeout)
{
    volatile uint16_t u16Len = 0;
	
    if(dv_UART.u8UartRecvCnt > 0)
    {
        u16Len = dv_UART.u8UartRecvCnt;
        memcpy( pData, dv_UART.u8UartData, u16Len );

            //清接收缓存
        dv_UART.u8UartRecvCnt = 0;
        memset( dv_UART.u8UartData, 0U, UART_TX_RX_BUFFER_SIZE);
        
    }
    else
    {
        u16Len = 0;
    }    
    return u16Len;
}
#endif

#if USE_UART_DMA
void UART3_IRQHandler(void)  //串口3中断服务程序
{
    if(RESET != usart_interrupt_flag_get(UART3, USART_INT_FLAG_IDLE))
    {
        /* clear IDLE flag */
        usart_data_receive(UART3);
        
        /* number of data received */
        dv_UART.u8UartRecvCnt = 200 - (dma_transfer_number_get(DMA1, DMA_CH2));
		
        /* disable DMA and reconfigure */
        dma_channel_disable(DMA1, DMA_CH2);
        dma_transfer_number_config(DMA1, DMA_CH2, 200);
        dma_channel_enable(DMA1, DMA_CH2);		
    }  

    //先读SR，再读DR以清USART_IT_IDLE标志
    USART_STAT0(UART3);
    USART_DATA(UART3);      
}

void USART2_IRQHandler(void)  //串口2中断服务程序
{
    if(RESET != usart_interrupt_flag_get(USART2, USART_INT_FLAG_IDLE))
    {
        /* clear IDLE flag */
        usart_data_receive(USART2);
        
        /* number of data received */
        dv_UART.u8UartRecvCnt = 200 - (dma_transfer_number_get(DMA0, DMA_CH2));
		
        /* disable DMA and reconfigure */
        dma_channel_disable(DMA0, DMA_CH2);
        dma_transfer_number_config(DMA0, DMA_CH2, 200);
        dma_channel_enable(DMA0, DMA_CH2);		
    }  

    //先读SR，再读DR以清USART_IT_IDLE标志
    USART_STAT0(USART2);
    USART_DATA(USART2);      
}

#else
void UART3_IRQHandler(void)                	//串口3中断服务程序
{
    if(usart_interrupt_flag_get(USART_X, USART_INT_FLAG_RBNE) != RESET)
    {
        /* 关空闲中断，以防再次进入中断不便处理 ------------------------------*/
        usart_interrupt_disable(USART_X, USART_INT_RBNE );

        dv_UART.u8UartData[dv_UART.u8UartRecvCnt] = usart_data_receive(USART_X);

        if(dv_UART.u8UartRecvCnt++ >= UART_TX_RX_BUFFER_SIZE)
        {
        	dv_UART.u8UartRecvCnt = UART_TX_RX_BUFFER_SIZE;
             if( dv_UART.xUartRxSem != NULL )
            {
                xSemaphoreGiveFromISR( dv_UART.xUartRxSem, &xHigherPriTaskWoken );
                portYIELD_FROM_ISR( xHigherPriTaskWoken );
            }
        }

        /* 清中断标志 --------------------------------------------------------*/
        usart_interrupt_flag_clear(USART_X, USART_INT_FLAG_RBNE);      
        /* 处理完毕后再次开空闲中断 ------------------------------------------*/
        usart_interrupt_enable(USART_X, USART_INT_RBNE);      
    }
    
    //先读SR，再读DR以清USART_IT_IDLE标志
    USART_STAT0(USART_X);
    USART_DATA(USART_X);  
}

#endif


static void USART_RX_EN_PIN_Ctrl(bool arg)
{	
	// bit_status BitVal;
	// BitVal = (arg)?(SET):(RESET);
	// gpio_init(GPIOC, GPIO_MODE_OUT_PP, GPIO_OSPEED_50MHZ, GPIO_PIN_12);
	// gpio_bit_write(GPIOC,GPIO_PIN_12,BitVal);
}


void init_dv_UART(void)
{    
    dv_UART.u8UartRecvCnt = 0;

    memset(dv_UART.u8UartData,0,UART_TX_RX_BUFFER_SIZE);

    dv_UART.fdeinit = BSP_UART_Deinit;
    dv_UART.finit = BSP_UART_Init;
    dv_UART.fclear = BSP_UART_Reg_Clear;
    dv_UART.fwrite_byte = BSP_UART_Byte_Send;
    dv_UART.fwrite_data = BSP_UART_Data_Send;
    dv_UART.fwrite_string = BSP_UART_String_Send;
    dv_UART.fread_data = BSP_UART_Data_Recv;
	dv_UART.fRxPinCtrl = USART_RX_EN_PIN_Ctrl;
}

#endif

